/*******************************************************************************
 * Copyright (c) 2008 Sylvain Sicard.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Sylvain Sicard - initial API and implementation
 ******************************************************************************/
package fr.jade.console.core;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import jline.ArgumentCompletor;
import jline.Completor;
import jline.ConsoleReader;
import jline.SimpleCompletor;

import org.objectweb.fractal.api.Component;

import fr.jade.base.JadeBaseObject;
import fr.jade.console.cmd.Boot;
import fr.jade.console.cmd.Call;
import fr.jade.console.cmd.Cd;
import fr.jade.console.cmd.Connect;
import fr.jade.console.cmd.Desc;
import fr.jade.console.cmd.Exit;
import fr.jade.console.cmd.Follow;
import fr.jade.console.cmd.GetEnvVar;
import fr.jade.console.cmd.Lc;
import fr.jade.console.cmd.Ls;
import fr.jade.console.cmd.PrintEnv;
import fr.jade.console.cmd.PrintLevel;
import fr.jade.console.cmd.Pwd;
import fr.jade.console.cmd.SetAttribute;
import fr.jade.console.cmd.SetEnvVar;
import fr.jade.console.cmd.Source;
import fr.jade.console.cmd.SwitchLevel;
import fr.jade.util.FractalNavigator;
import fr.jade.util.JadeException;

public class JTerm extends JadeBaseObject{

  protected Map<String, Command> commands = null;
	protected Environment env = null;
	
	public JTerm(){
	  this.commands = new HashMap<String, Command>();
		this.env = new Environment();
		env.setEnvVar( "current", new Object() );
		env.setEnvVar( "shell", this );
		registerCommands();
	}
	
	public JTerm( String[] args ){
		// not yet implemented
	}
	
	protected void registerCommands(){
	 new Boot().register(commands);
	 new Call().register(commands);
	 new Cd().register(commands);
	 new Connect().register(commands);
	 new Exit().register(commands);
	 new GetEnvVar().register(commands);
	 new Lc().register(commands);
	 new Ls().register(commands);
	 new PrintEnv().register(commands);
	 new PrintLevel().register(commands);
	 new Pwd().register(commands);
	 new SetAttribute().register(commands);
	 new SetEnvVar().register(commands);
	 new Source().register(commands);
	 new SwitchLevel().register(commands);
	 new Help().register(commands);
	 new Desc().register(commands);
	 new Follow().register(commands);
	}
	
	protected Map<String, Command> getConsoleCommands(){
	  return commands;
	}
	public void start(String[] args){
	  for(String cmdLine : args){
	    try{
        evaluateCmd( cmdLine );
      }catch(Throwable e){
        e.printStackTrace();
      }
	  }
		try{
//			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//			while(true){
//				log( " >" );
//				String cmdLine = in.readLine();
//				if ( !cmdLine.equals( "" ) ){
//					try{
//						evaluateCmd( cmdLine );
//					}catch(Exception e){
//						e.printStackTrace();
//					}
//				}
//			}
		  
		  ConsoleReader reader = new ConsoleReader();
	    List<Completor> completors = new LinkedList<Completor>();
	    completors.add(new SimpleCompletor(commands.keySet().toArray(new String[0])));
	    completors.add(new FractalCompletor(env));
	    reader.addCompletor(new ArgumentCompletor(completors));
	    String cmdLine;
	    while (true) {
	      cmdLine = reader.readLine(beautifiedPrompt(getPrompt()));
        if ( !cmdLine.equals( "" ) ){
          try{
            evaluateCmd( cmdLine );
          }catch(Exception e){
            e.printStackTrace();
          }
        }	      
	    }
		}catch(Exception e){
			log("Fatal error in JTerm");
			e.printStackTrace();
		}
	}
	
	public void evaluateCmd(String cmdLine){
		String[] cmd = cmdLine.split(" ");
		try{
			Command c = commands.get(cmd[0]);
			if(c == null) {
			  System.err.println("JTerm: "+cmd[0]+" command not found");
			}else{
			  c.execute(cmd, env);
			}
		}catch(Throwable e){
			System.out.println("JTerm # Error");
			if(e instanceof JadeException){
			  log((JadeException)e);
			}else{
			  e.printStackTrace();
			}
		}
	}
	
	private String getPrompt(){
	  String prompt = "";
	  Component current = (Component)env.getEnvVar("current");
	  if(current != null)prompt = FractalNavigator.getName(current);
	  return prompt;
	}
	private String beautifiedPrompt(String barePrompt)
  {
    String prompt = barePrompt + "> ";
    prompt = ColorPrinter.getColoredMessage(prompt, ColorPrinter.PROMPT);
    return prompt;
  }
}
